﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
using System.Net;
using System.ComponentModel;
using System.IO;

using XPTable;
using XPTable.Editors;
using XPTable.Events;
using XPTable.Models;
using XPTable.Renderers;
using XPTable.Sorting;

using Un4seen.Bass;

namespace WinBird
{
    public partial class MainForm
    {
        Thread threadAudio;

        Color shrink = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(35)))), ((int)(((byte)(44)))));

        bool manualStop = false;

        private void Audio()
        {
            threadAudio = new Thread(ThreadAudio);
            threadAudio.Priority = ThreadPriority.Normal;
            threadAudio.Start();
        }

        private void ThreadAudio()
        {
            this.listFriends.Invoke(new delegateAudio(this.getAudio), new object[] { api.UserID, 0 });
            this.listFriends.Invoke(new delegateGetAlbums(this.getAlbums), new object[] { api.UserID });
        }
        public delegate void delegateAudio(int uid = 0, int audio_id = 0);
        public delegate void delegateGetAlbums(int uid = 0);

        private void getAudio(int uid = 0, int album_id = 0)
        {
            this.listAudio.TableModel.Rows.Clear();
            this.searchTrue = false;

            try
            {
                string[,] arr = new string[,] { { "uid", uid.ToString() } };

                if (album_id > 0 && uid > 0) { arr = new string[,] { { "uid", uid.ToString() }, { "album_id", album_id.ToString() } }; }
                else if (album_id > 0) { arr = new string[,] { { "album_id", album_id.ToString() } }; }

                Array[] result = api.getApi("audio.get", "audio",
                    new string[] { "aid", "owner_id", "artist", "title", "duration", "url" },
                    arr
                );

                int i = 0;
                int num = 1;

                foreach (string[] content in result)
                {
                    this.listAudio.TableModel.Rows.Add(new Row());
                    this.listAudio.TableModel.Rows[i].Tag = content[5];
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(num));
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(content[0]));
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(""));
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(content[2] + " - " + content[3]));
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(this.Duration(int.Parse(content[4]))));

                    if (api.UserID == api.homeUserID)
                    {
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell("X"));
                        this.listAudio.TableModel.Rows[i].Cells[5].ForeColor = Color.Red;
                    }
                    else
                    {
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell("+"));
                        this.listAudio.TableModel.Rows[i].Cells[5].ForeColor = Color.Green;
                    }
                    this.listAudio.TableModel.Rows[i].Cells[5].Tag = i;

                    //Progress
                    this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(0));


                    if (Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PLAYING || Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PAUSED)
                    {
                        if (int.Parse(content[0]) == currentID)
                        {
                            this.listAudio.TableModel.Rows[i].Cells[2].Text = "4";
                        }
                    }

                    this.listAudio.TableModel.Rows[i].Cells[2].Font = new System.Drawing.Font("Webdings", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(2)));

                    num++;
                    i++;
                }

                this.listFriends.Cursor = System.Windows.Forms.Cursors.Default;

                this.listAudio.TableModel.Dispose();
            }
            catch (Exception)
            {
                err.setError("Ошибка при получении данных");
            }
        }

        private void getAlbums(int uid = 0)
        {
            try
            {
                this.tabControl.Controls.Clear();
                Array[] result = api.getApi("audio.getAlbums", "album",
                    new string[] { "owner_id", "album_id", "title" },
                    new string[,] { { "uid", uid.ToString() } });

                //Все аудиозаписи
                TabPage tabPageAll = new System.Windows.Forms.TabPage();
                tabPageAll.Text = "Все аудиозаписи";
                tabPageAll.Tag = "0";
                this.tabControl.Controls.Add(tabPageAll);

                foreach (string[] content in result)
                {
                    TabPage tabPage = new System.Windows.Forms.TabPage();
                    tabPage.Text = content[2];
                    tabPage.Tag = content[1];
                    this.tabControl.Controls.Add(tabPage);
                }
            }
            catch (Exception)
            {
                err.setError("Не удалось загрузить список альбомов");
            }

        }

        private void tabControl_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.tabControl.Cursor = System.Windows.Forms.Cursors.WaitCursor;

                try
                {
                    this.getAudio(api.UserID, int.Parse(this.tabControl.SelectedTab.Tag.ToString()));
                }
                catch (Exception)
                {
                    err.setError("Произошла ошибка при открытии альбома");
                }

                this.tabControl.Cursor = System.Windows.Forms.Cursors.Default;
            }
        }

        private string Duration(int time)
        {
            string hour = "";

            if (time >= 3600)
            {
                time = time % 3600;
                double h = time / 3600;
                hour = Math.Floor(h) + ":";
            }

            double m = time / 60;
            time = time % 60;
            string min = Math.Floor(m).ToString() + ":";

            double s = time;
            string sec = Math.Floor(s).ToString();

            if (Math.Floor(s) < 10)
            {
                sec = "0" + Math.Floor(s).ToString();
            }

            return String.Format("{0}{1}{2}", hour, min, sec);
        }

        private void listAudio_ClientSizeChanged(object sender, EventArgs e)
        {
            this.audio_titleColumn.Width = this.listAudio.Width
                - audio_numColumn.Width
                - audio_playingColumn.Width
                - audio_durationColumn.Width
                - audio_buttonColumn.Width
                - audio_progressColumn.Width
                - 50;
        }

        private void listAudio_CellDoubleClick(object sender, XPTable.Events.CellMouseEventArgs e)
        {
            this.Play(e.Row);
        }

        private void timerBass_Tick(object sender, EventArgs e)
        {
            switch (Bass.BASS_ChannelIsActive(uBass.stream))
            {
                case BASSActive.BASS_ACTIVE_PAUSED:
                    {
                        break;
                    }
                case BASSActive.BASS_ACTIVE_PLAYING:
                    {
                        string sb = string.Empty;
                        sb = Bass.BASS_ChannelGetPosition(uBass.stream).ToString();

                        trackBarPosition.Maximum = int.Parse(((Bass.BASS_ChannelBytes2Seconds(uBass.stream, Bass.BASS_ChannelGetLength(uBass.stream)).ToString().Split(',', '.'))[0]));
                        trackBarPosition.Value = int.Parse(((Bass.BASS_ChannelBytes2Seconds(uBass.stream, Bass.BASS_ChannelGetPosition(uBass.stream)).ToString().Split(',', '.'))[0]));

                        int time = (int)Bass.BASS_ChannelBytes2Seconds(uBass.stream, Bass.BASS_ChannelGetPosition(uBass.stream));

                        this.audioTime.Text = Duration(time) + " / " + fullTime;

                        break;
                    }
                case BASSActive.BASS_ACTIVE_STALLED:
                    {
                        if (manualStop != true)
                        {
                            Bass.BASS_ChannelStop(uBass.stream);
                            Bass.BASS_StreamFree(uBass.stream);
                            this.Next();
                        }
                        break;
                    }
                case BASSActive.BASS_ACTIVE_STOPPED:
                    {
                        if (uBass.stream != 0 && manualStop != true)
                        {
                            this.Next();
                        }

                        break;
                    }
            }
        }

        int currentIndex = 0;
        int currentID = 0;
        string fullTime = "0:00";
        private void Play(int index)
        {
            this.buttonPause.Visible = true;
            this.buttonPlay.Visible = false;

            try
            {
                foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
                {
                    r.Cells[2].Text = "";
                }

                currentIndex = index;

                this.listAudio.TableModel.Rows[index].Cells[2].Text = "4";

                currentID = int.Parse(this.listAudio.TableModel.Rows[index].Cells[1].Text);

                string url = this.listAudio.TableModel.Rows[index].Tag.ToString();

                this.audioText.Text = this.listAudio.TableModel.Rows[index].Cells[3].Text;

                this.listAudio.EnsureVisible(index, 3);

                fullTime = this.listAudio.TableModel.Rows[currentIndex].Cells[4].Text;

                uBass.Play(url);

                manualStop = false;
            }
            catch (Exception)
            {
                err.setError("Не удалось воспроизвести аудиозапись");
            }
        }

        Random r = new Random();
        private void Next()
        {
            if (this.checkShuffle.Checked == true)
            {
                int newIndex = r.Next(0, this.listAudio.TableModel.Rows.Count - 1);

                currentIndex = (newIndex != currentIndex) ? newIndex : newIndex + 1;
            }
            else
            {
                currentIndex++;
            }

            if (currentIndex > this.listAudio.TableModel.Rows.Count - 1)
            {
                currentIndex = 0;
            }

            this.Play(currentIndex);
        }

        private void Back()
        {
            if (this.checkShuffle.Checked == true)
            {
                int newIndex = r.Next(0, this.listAudio.TableModel.Rows.Count - 1);

                currentIndex = (newIndex != currentIndex) ? newIndex : newIndex - 1;
            }
            else
            {
                currentIndex--;
            }

            if (currentIndex < 0)
            {
                currentIndex = 0;
            }

            this.Play(currentIndex);
        }

        private void trackBarPosition_Scroll(object sender, EventArgs e)
        {
            Bass.BASS_ChannelSetPosition(uBass.stream, (double)trackBarPosition.Value);
        }

        private void trackBarPosition_MouseDown(object sender, MouseEventArgs e)
        {
            trackBarPosition.Value = (int)trackBarPosition.Maximum * e.X / trackBarPosition.Width;
            Bass.BASS_ChannelSetPosition(uBass.stream, (double)trackBarPosition.Value);
        }

        //float getVolume;
        private void trackBarVolume_Scroll(object sender, EventArgs e)
        {
            //getVolume = (float)Math.Floor(Bass.BASS_GetVolume());

            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_STREAM, (int)trackBarVolume.Value);
        }

        private void buttonBack_Click(object sender, EventArgs e)
        {
            this.Back();
        }

        private void buttonPlay_Click(object sender, EventArgs e)
        {
            if (Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PAUSED)
            {
                this.buttonPause.Visible = true;
                this.buttonPlay.Visible = false;
                Bass.BASS_ChannelPlay(uBass.stream, false);
            }
            else
            {
                if (this.checkShuffle.Checked == true)
                {
                    int newIndex = r.Next(0, this.listAudio.TableModel.Rows.Count - 1);

                    currentIndex = (newIndex != currentIndex) ? newIndex : newIndex + 1;
                }
                this.Play(currentIndex);
            }
        }

        private void buttonPause_Click(object sender, EventArgs e)
        {
            if (Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PLAYING)
            {
                this.buttonPlay.Visible = true;
                this.buttonPause.Visible = false;
                Bass.BASS_ChannelPause(uBass.stream);
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            if (Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PLAYING || Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PAUSED)
            {
                manualStop = true;

                this.buttonPlay.Visible = true;
                this.buttonPause.Visible = false;

                foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
                {
                    r.Cells[2].Text = "";
                }

                currentID = 0;

                this.trackBarPosition.Value = 0;
                this.audioText.Text = "";
                this.audioTime.Text = "";

                Bass.BASS_ChannelStop(uBass.stream);
                Bass.BASS_StreamFree(uBass.stream);
            }
        }

        private void buttonNext_Click(object sender, EventArgs e)
        {
            this.Next();
        }

        private void listAudio_CellButtonClicked(object sender, XPTable.Events.CellButtonEventArgs e)
        {
            try
            {
                int index = int.Parse(e.Cell.Tag.ToString());

                int aid = int.Parse(this.listAudio.TableModel.Rows[index].Cells[1].Text);

                string title = this.listAudio.TableModel.Rows[index].Cells[3].Text;

                if (api.UserID == api.homeUserID && this.searchTrue == false)
                {
                    Array[] result = api.getApi("audio.delete", "response", null,
                        new string[,] { { "aid", aid.ToString() }, { "oid", api.UserID.ToString() } });

                    foreach (string[] content in result)
                    {
                        if (content[0] == "1")
                        {
                            this.listAudio.TableModel.Rows[index].Dispose();

                            int i = 0;
                            int num = 1;
                            foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
                            {
                                r.Cells[5].Tag = i;
                                r.Cells[0].Data = num;
                                i++;
                                num++;
                            }
                        }
                    }
                }
                else if (this.searchTrue == true)
                {
                    Array[] result = api.getApi("audio.add", "response", null,
                        new string[,] { { "aid", aid.ToString() }, { "oid", this.listAudio.TableModel.Rows[index].Cells[0].Tag.ToString() } });

                    foreach (string[] content in result)
                    {
                        if (content[0] == "1")
                        {
                            this.listAudio.TableModel.Rows[index].BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(38)))), ((int)(((byte)(53)))), ((int)(((byte)(64)))));
                            this.listAudio.TableModel.Rows[index].ForeColor = Color.White;
                        }
                    }
                }
                else
                {
                    Array[] result = api.getApi("audio.add", "response", null,
                        new string[,] { { "aid", aid.ToString() }, { "oid", api.UserID.ToString() } });

                    foreach (string[] content in result)
                    {
                        if (content[0] == "1")
                        {
                            this.listAudio.TableModel.Rows[index].BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(38)))), ((int)(((byte)(53)))), ((int)(((byte)(64)))));
                            this.listAudio.TableModel.Rows[index].ForeColor = Color.White;
                        }
                    }

                }

            }
            catch (Exception)
            {
                err.setError("Ошибка при инициализации команды");
            }
        }

        bool searchTrue = false;
        private void boxSearch_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (e.KeyChar.Equals((char)13) && this.boxSearch.Text != "Поиск")
                {
                    this.listFriends.Cursor = System.Windows.Forms.Cursors.WaitCursor;
                    this.listAudio.TableModel.Rows.Clear();

                    Array[] result = api.getApi("audio.search", "audio",
                        new string[] { "aid", "owner_id", "artist", "title", "duration", "url" },
                        new string[,] { { "q", this.boxSearch.Text }, { "auto_complete", "1" }, { "count", "200" } }
                        );

                    int i = 0;
                    int num = 1;

                    foreach (string[] content in result)
                    {
                        this.listAudio.TableModel.Rows.Add(new Row());
                        this.listAudio.TableModel.Rows[i].Tag = content[5];
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(num));
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(content[0]));
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(""));
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(content[2] + " - " + content[3]));
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(this.Duration(int.Parse(content[4]))));


                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell("+"));
                        this.listAudio.TableModel.Rows[i].Cells[5].ForeColor = Color.Green;
                        this.listAudio.TableModel.Rows[i].Cells[0].Tag = content[1];

                        this.listAudio.TableModel.Rows[i].Cells[5].Tag = i;

                        //Progress
                        this.listAudio.TableModel.Rows[i].Cells.Add(new Cell(0));


                        if (Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PLAYING || Bass.BASS_ChannelIsActive(uBass.stream) == BASSActive.BASS_ACTIVE_PAUSED)
                        {
                            if (int.Parse(content[0]) == currentID)
                            {
                                this.listAudio.TableModel.Rows[i].Cells[2].Text = "4";
                            }
                        }

                        this.listAudio.TableModel.Rows[i].Cells[2].Font = new System.Drawing.Font("Webdings", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(2)));

                        num++;
                        i++;
                    }

                    this.listFriends.Cursor = System.Windows.Forms.Cursors.Default;

                    this.searchTrue = true;

                    this.listAudio.TableModel.Dispose();
                }
            }
            catch (Exception)
            {
                err.setError("Ошибка при получении данных");
            }
        }

        private void checkBoxSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBoxSelectAll.Checked == true)
            {
                foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
                {
                    r.Cells[3].Checked = true;
                }
            }
            else
            {
                foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
                {
                    r.Cells[3].Checked = false;
                }
            }
        }

        string[] download;
        private void buttonDownload_Click(object sender, EventArgs e)
        {
            int iChecked = 0;
            foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
            {
                if (r.Cells[3].Checked == true)
                {
                    iChecked++;
                }
            }


            if (iChecked > 0)
            {
                this.saveDownload.ShowDialog();
                if (this.saveDownload.SelectedPath != "")
                {
                    this.audio_progressColumn.Visible = true;

                    Thread threadDownload = new Thread(downloadThread);
                    threadDownload.Priority = ThreadPriority.Lowest;
                    threadDownload.Start();
                }
                else
                {
                    err.setError("Вы не отметили ни одной аудиозаписи для скачивания");
                }
            }
        }

        private void downloadThread() {
            this.listAudio.Invoke(new delegateThreadDownload(this.downloadFunc));
        }
        public delegate void delegateThreadDownload();

        private void downloadFunc()
        {
            foreach (XPTable.Models.Row r in this.listAudio.TableModel.Rows)
            {
                if (File.Exists(this.saveDownload.SelectedPath + "\\" + r.Cells[1].Text + ".mp3"))
                {
                    r.Cells[6].Data = 100;
                }

                if (r.Cells[3].Checked == true)
                {
                    try
                    {
                        if (!File.Exists(this.saveDownload.SelectedPath + "\\" + r.Cells[1].Text + ".mp3"))
                        {
                            using (WebClient download = new WebClient())
                            {
                                download.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
                                download.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                                download.DownloadFileAsync(new Uri(r.Tag.ToString()), this.saveDownload.SelectedPath + "\\" + r.Cells[1].Text + ".mp3.tmp", r.Index);
                            }
                        }
                    }
                    catch (WebException e)
                    {
                        err.setError("Произошла ошибка при загрузке аудиозаписи");
                    }
                }
            }
        }

        private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            this.listAudio.TableModel.Rows[int.Parse(e.UserState.ToString())].Cells[6].Data = e.ProgressPercentage;
        }

        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            string file = this.listAudio.TableModel.Rows[int.Parse(e.UserState.ToString())].Cells[1].Text+".mp3";

            FileInfo fi = new FileInfo(this.saveDownload.SelectedPath+"\\"+file+".tmp");

            if (fi.Exists)
            {
                fi.MoveTo(this.saveDownload.SelectedPath + "\\" + file);
                this.listAudio.TableModel.Rows[int.Parse(e.UserState.ToString())].Cells[6].Data = 100;
            }
            else
            {
                this.listAudio.TableModel.Rows[int.Parse(e.UserState.ToString())].Cells[6].Data = 0;
            }
        }
    }
}
